package com.zjpavt.client.extenddevice;

import com.zjpavt.client.enums.ExtendDeviceEnum;
import com.zjpavt.client.extenddevice.voltagecurrent.IHumidityDevice;
import com.zjpavt.client.extenddevice.voltagecurrent.ITemperatureAndHumidityDevice;
import com.zjpavt.client.extenddevice.voltagecurrent.ITemperatureDevice;
import com.zjpavt.client.nativemethod.JnIMethod;
import com.zjpavt.client.util.*;
import io.netty.util.concurrent.DefaultThreadFactory;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.text.DecimalFormat;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 温湿度传感器
 *
 * @author zyc
 */
@Slf4j
public class TemperatureAndHumiditySensor extends AbstractExtendDevice implements ITemperatureAndHumidityDevice {
    public static final String TEMPERATURE_PATH = ClientConfig.INI_TEMPERATURE_PATH;
    public static final String TMP_SECTION = "tmp_data";
    public static final String TEMPERATURE = "tmp";
    public static final String HUMIDITY = "hum";
    public static final DecimalFormat tmpFormet = new DecimalFormat("#0.0");
    private static final ScheduledThreadPoolExecutor tmpThreadPool = new ScheduledThreadPoolExecutor(1, new DefaultThreadFactory("tmpPool"));
    /**
     * 温度值
     */
    private double temperature = Double.MIN_VALUE;
    /**
     * 湿度值
     */
    private double humidity = Double.MIN_VALUE;

    /**
     * 温度阈值的KEY 保存在properties
     */
    public static final String FAN_THRESHOLD_PROPERTIES_KEY = "fan_temperature_threshold";

    public static final Pattern TMP_PATTERN =
        Pattern.compile("<AT_T/H_(?<tmp>[0-9]{4})/(?<hum>[0-9]{4})>");
    private void updateInformationTask() {
        updateInformation();
        tmpThreadPool.schedule(this::updateInformationTask,20, TimeUnit.SECONDS);
    }

    public TemperatureAndHumiditySensor updateInformation() {
        String information = JnIMethod.sendMessage2ExtendDeviceByRs485(115200, getExtendNum(), "<AT_READ>", 200);
        if (information == null) {
            getUnderDeviceInteractionBean().interactionFail();
            return this;
        } else {
            getUnderDeviceInteractionBean().interactionSuccess();
        }
        Matcher matcher = TMP_PATTERN.matcher(information);
        if (matcher.matches()) {
            this.temperature = Double.parseDouble(matcher.group("tmp")) /10;
            this.humidity = Double.parseDouble(matcher.group("hum"))/10;
        } else {
            log.error("update temperature fail");
        }
        return this;
    }

    /**
     * 机柜内启动风扇等措施的阈值
     */
    private volatile int temperatureThreshold = 0;

    public TemperatureAndHumiditySensor(int extNum) {
        super(extNum,ExtendDeviceEnum.TMP);
        getThresholdFromProperties();
    }

    private void getThresholdFromProperties() {
        String thresholdString = null;
        try {
            thresholdString = PropertiesUtil.getPropertiesDefault(FAN_THRESHOLD_PROPERTIES_KEY);
            temperatureThreshold = Integer.parseInt(thresholdString);
        } catch (Exception e) {
            log.error("get temperature threshold:" + thresholdString);
        }
    }

    @Override
    public ITemperatureDevice updateTmpInformation() {
        return updateInformation();
    }

    /**
     * 获取温度阈值 单位 1°C
     * @return
     */
    @Override
    public int getTemperatureThreshold() {
        return temperatureThreshold;
    }

    /**
     * 获取温度
     * @return
     */
    @Override
    public double getTemperature() {
        return this.temperature;
    }

    /**
     * 获取湿度
     * @return
     */
    @Override
    public double getHumidity() {
        return this.humidity;
    }

    /**
     * 设置温度阈值 单位 1°C
     * @param temperatureThreshold
     */
    @Override
    public synchronized boolean setTemperatureThreshold(double temperatureThreshold) {
        try {
            if (changeTemperatureThreshold((int)temperatureThreshold)) {
                PropertiesUtil.setPropertyOrReplaceDefault(FAN_THRESHOLD_PROPERTIES_KEY,String.valueOf(temperatureThreshold));
                this.temperatureThreshold = (int)temperatureThreshold;
                return true;
            } else {
                return false;
            }
        } catch (IOException e) {
            log.error(LoggerUtil.convertException2String(e));
            return false;
        }
    }

    public static final DecimalFormat TEMPERATURE_THRESHOLD_FORMATE = new DecimalFormat("0000");
    /**
     * 修改温度阈值
     * @param temperatureThreshold
     */
    private synchronized boolean changeTemperatureThreshold(int temperatureThreshold) {
        String message = "<AT_SET_" + TEMPERATURE_THRESHOLD_FORMATE.format(temperatureThreshold * 10) + ">";
        String setThresholdResult = JnIMethod
                                    .sendMessage2ExtendDeviceByRs485(115200, getExtendNum(), message, 200);
        if (setThresholdResult == null || "".equals(setThresholdResult)) {
            log.error("set temperature threshold fail");
            return false;
        } else {
            log.info("changeTemperatureThreshold: " + setThresholdResult);
            return true;
        }
    }

    @Override
    public IHumidityDevice updateHumidityInformation() {
        return updateInformation();
    }
}
